import Modal from './Modal';
import ServiceError from './ServiceError';
import {PlainObject,preprocessor} from '../../../../types';
import {getUid} from '../../../util/common';
import {rootContainerVue,renders} from '../../js/app/rootContainer';
//region 定义接口
/**
 * 传给api的选项
 * @property {string} title					标题
 * @property {string} content				内容
 * @property {string} [contentClass]		内容的class
 * @property {PlainObject} [contentStyle]	内容的style
 * @property {string|number} [horizontalGap]	水平最小预留长度
 * @property {string|number} [verticalGap]		垂直最小预留长度
 * @property {string} [confirmText]			确定按钮文字
 * @property {string} [closeText]			取消按钮文字
 * @property {boolean} [closable]			是否有关闭按钮
 * @property {preprocessor} [beforeClose]	关闭前处理器, 支持返回promise, 返回false表示禁止关闭
 * @property {number} [max]					最大实例数, 0表示不限制
 * @property {boolean} [override]			替换最早的提示, 默认true
 */
export interface PassOptions{
	title:string,
	content:string,
	contentClass?:string,
	contentStyle?:PlainObject,
	horizontalGap?:string|number,
	verticalGap?:string|number,
	confirmText?:string,
	closeText?:string,
	closable?:boolean,
	beforeClose?:preprocessor,
	max?:number,
	override?:boolean,
}
export interface Options extends PassOptions{
	uid:string,
	max:number,
	value:boolean,
	transitionAppear:boolean,
	onConfirm?:() => void,
	onClose?:() => void,
	onHidden?:() => void,
}
export interface PassServiceOptions{
	content:string,
	info:string,
}
export interface ServiceOptions extends PassServiceOptions{
	uid:string,
	value:boolean,
	onHidden?:() => void,
}
/**
 * 弹窗方法
 * @param {PassOptions} opt 选项
 * @return {Promise<void>}	确定进入then, 取消进入catch
 */
export interface AlertFunction{
	(opt:PassOptions):Promise<boolean>
}
/**
 * 定义接口
 * @property {AlertFunction} alert		提示弹窗
 * @property {AlertFunction} confirm	确认弹窗
 * @property {(opt:PassServiceOptions) => Promise<void>} serviceError	服务器错误
 */
export interface ModalApi{
	alert:AlertFunction,
	confirm:AlertFunction,
	serviceError:(opt:PassServiceOptions) => Promise<void>,
}
//endregion

//弹窗实例
const container:Array<Options>=[];
//服务器错误实例
const serviceErrorContainer:Array<ServiceOptions>=[];
//渲染函数
renders.push(function(h){
	return h('div',{
		staticClass:'lexmis-ModalContainer',
	},container.map((opt) => {
		return h(Modal,{
			props:opt,
			key:opt.uid,
			on:{
				confirm:opt.onConfirm!,
				close:opt.onClose!,
				hidden:opt.onHidden!,
			}
		},opt.content);
	}).concat(serviceErrorContainer.map((opt) => {
		return h(ServiceError,{
			props:opt,
			key:opt.uid,
			on:{
				hidden:opt.onHidden!,
			}
		});
	})));
});
rootContainerVue.$forceUpdate();
//标准化选项
function normalizedOptions(opt:PassOptions,extend?:PlainObject):Options{
	return Object.assign({
		uid:getUid(),
		value:true,
		transitionAppear:true,
		max:0,
		override:true,
	},opt,extend);
}
//不预定义类型的提示
function realShow(option:Options):Promise<boolean>{
	const addOption=() => {
		return new Promise<boolean>((resolve) => {
			let result:boolean;
			option.onConfirm=() => {
				result=true;
				option.value=false;
				rootContainerVue.$forceUpdate();
			};
			option.onClose=() => {
				result=false;
			};
			option.onHidden=() => {
				const pos=container.indexOf(option);
				if(pos!==-1){
					container.splice(pos,1);
				}
				rootContainerVue.$forceUpdate();
				resolve(result);
			};
			container.unshift(option);
			rootContainerVue.$forceUpdate();
		});
	};
	if(option.max>=1&&container.length>=option.max){
		if(option.override){
			container.pop()!.onHidden!();
			return addOption();
		}else{
			return Promise.reject(new Error(`弹窗达到最大个数${option.max}!`));
		}
	}else{
		return addOption();
	}
}
function alert(opt:PassOptions):Promise<boolean>{
	return realShow(normalizedOptions(opt,{
		closable:false,
	}));
}
function confirm(opt:PassOptions):Promise<boolean>{
	return realShow(normalizedOptions(opt));
}
function serviceError(opt:PassServiceOptions):Promise<void>{
	const option:ServiceOptions=Object.assign({
		uid:getUid(),
		value:true,
	},opt);
	return new Promise<void>((resolve) => {
		option.onHidden=() => {
			const pos=serviceErrorContainer.indexOf(option);
			if(pos!==-1){
				serviceErrorContainer.splice(pos,1);
			}
			rootContainerVue.$forceUpdate();
			resolve();
		};
		serviceErrorContainer.unshift(option);
		rootContainerVue.$forceUpdate();
	});
}
export default Object.assign(Modal,{
	alert,
	confirm,
	serviceError,
}) as (ModalApi&typeof Modal);
